package com.sinosoft.cloud.access.net;

import com.sinosoft.cloud.access.codec.AccessDecoder;
import com.sinosoft.cloud.access.handler.*;
import io.netty.channel.Channel;
import io.netty.channel.ChannelPipeline;

/**
 * cloud-netty
 *
 * @title: cloud-netty
 * @package: com.sinosoft.cloud.access.net
 * @author: yangming
 * @date: 2017/12/2 下午2:02
 */
public class AccessChannelInitializer extends AbstractAccessInitializer {

    @Override
    protected void initChannel(Channel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();
        addAccessHandler(pipeline);
    }

    /**
     * 初始化整个Access的整个流程,
     * 1. 现进行Decoder(处理报文头,将消息接受完整)
     * 2. 进行非标准报文的校验.
     * 4. 非标准报文->标准报文->TranData(非标准报文->标准报文->TranData->Service-返回标准报文->返回非标准报文)
     * 5. 进行路由处理.
     * 6. 服务调用,(熔断再路由)
     * 7. 判断进行再路由处理
     * 8. 进行加密
     * 9. 进行报文头处理
     *
     * @param pipeline
     */
    private void addAccessHandler(ChannelPipeline pipeline) {
        /*现进行Decoder(处理报文头,将消息接受完整)*/
        initAccessDecoder(pipeline);
        /*第二步待添加*/
        initRawCheck(pipeline);
        /*解密处理*/
        initCryptoHandler(pipeline);
        /*非标准报文到标准报文转化*/
        initMessageToTranDataHandler(pipeline);
        /*处理消息持久化*/
        initMessageInPersistentHandler(pipeline);
        /*处理限流*/
        initCircuitBreakerHandler(pipeline);
        /*路由处理*/
        initRouter(pipeline);
        /*调用远端微服务*/
        initMicroserviceHandler(pipeline);
        /*进行TranData转换成银行报文*/
        initTranDataToMessageHandler(pipeline);
        /*报文后处理，循环修改节点*/
        initAfterTransform(pipeline);
        /*处理消息持久化*/
        initMessageOutPersistentHandler(pipeline);
        /*报文加密*/
        initMessageEncryptHandler(pipeline);
        /*增加报文头*/
        initMessageAddHeadHandler(pipeline);
        /*最后完成所有内容*/
        initCompleteHandler(pipeline);

    }

    /**
     * 完成整个处理
     *
     * @param pipeline
     */
    private void initCompleteHandler(ChannelPipeline pipeline) {
        CompleteHandler handler = new CompleteHandler();
        pipeline.addLast(handler);
    }

    /**
     * @param pipeline
     */
    private void initTranDataToMessageHandler(ChannelPipeline pipeline) {
        TranDataToMessageHandler handler = new TranDataToMessageHandler();
        addHandler(pipeline, handler);
    }

    /**
     * @param pipeline
     */
    private void initMicroserviceHandler(ChannelPipeline pipeline) {
        MicroserviceHandler handler = new MicroserviceHandler();
        addHandler(pipeline, handler);
    }

    /**
     * @param pipeline
     */
    private void initMessageInPersistentHandler(ChannelPipeline pipeline) {
        MessagePersistentHandler handler = new MessagePersistentHandler();
        handler.setMessageType("In");
        addHandler(pipeline, handler);
    }

    /**
     * @param pipeline
     */
    private void initMessageOutPersistentHandler(ChannelPipeline pipeline) {
        MessagePersistentHandler handler = new MessagePersistentHandler();
        handler.setMessageType("Out");
        addHandler(pipeline, handler);
    }


    /**
     * 断路器处理
     *
     * @param pipeline
     */
    private void initCircuitBreakerHandler(ChannelPipeline pipeline) {
        CircuitBreakerHandler handler = new CircuitBreakerHandler();
        addHandler(pipeline, handler);

    }

    /**
     * 添加路由处理
     *
     * @param pipeline
     */
    private void initRouter(ChannelPipeline pipeline) {
        RouterHandler handler = new RouterHandler();
        addHandler(pipeline, handler);
    }

    /**
     * 进行格式转换
     *
     * @param pipeline
     */
    private void initMessageToTranDataHandler(ChannelPipeline pipeline) {
        MessageToTranDataHandler handler = new MessageToTranDataHandler();
        addHandler(pipeline, handler);
    }

    /**
     * 进行非标准报文到标准报文的转化
     *
     * @param pipeline
     */
    private void initCryptoHandler(ChannelPipeline pipeline) {
        CryptoHandler handler = new CryptoHandler();
        addHandler(pipeline, handler);
    }

    /**
     * 进行银行报文的前置校验
     *
     * @param pipeline
     */
    private void initRawCheck(ChannelPipeline pipeline) {

    }

    private void initAccessDecoder(ChannelPipeline pipeline) {
        AccessDecoder accessDecoder = new AccessDecoder();
        accessDecoder.setAccessName(this.getAccessName());
        accessDecoder.setPort(this.getPort());
        pipeline.addLast(accessDecoder);
    }


    private void initMessageAddHeadHandler(ChannelPipeline pipeline) {
        DcoderHandler dcoderHandler = new DcoderHandler();
        addHandler(pipeline, dcoderHandler);
    }

    private void initMessageEncryptHandler(ChannelPipeline pipeline) {
        EncryptHandler handler = new EncryptHandler();
        addHandler(pipeline, handler);
    }

    private void initAfterTransform(ChannelPipeline pipeline) {
        AfterTransformHandler afterTransformHandler = new AfterTransformHandler();
        addHandler(pipeline, afterTransformHandler);
    }

    private void addHandler(ChannelPipeline pipeline, AbstractHandler handler) {
        handler.setAccessName(this.getAccessName());
        handler.setPort(this.getPort());
        pipeline.addLast(handler);
    }
}
